/*
    <one line to give the library's name and an idea of what it does.>
    Copyright (C) 2013  Guillaume <email>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/


#ifndef UQSAMPLERPDF_H
#define UQSAMPLERPDF_H

#include <msSamplerExplicit.h>
#include <msUtilitiesBayes.h>

namespace atomism
{
class uqSamplerPdf : public msSamplerExplicit
{
 
protected:	
   
      static msRegistrar Registrar;
      static bool  isSamplerPdfRegisteredInPython;
      static msRegister* createInstance() { return new uqSamplerPdf; }
      void registryInPython();
      
      uqSamplerPdf() : msSamplerExplicit() { constructVar("uqSamplerPdf","SamplerPdf","sampler of pdf"); }  
      
public:
  
     void update()  { msSamplerExplicit::update();
                      };
		     
     void initialize() {  msSamplerExplicit::initialize();
			  msTreeMapper::declareChild<msGeneralizedCoordinates>(UqParameters,msGeneralizedCoordinates::New(msUnitsManager::New("")),"UqParameters");
			  msTreeMapper::declareChild<msScalarFunction>(Model,msScalarFunction::New(""),"Model");
			  };
			    
     static boost::shared_ptr<uqSamplerPdf> New(){
             
               boost::shared_ptr<uqSamplerPdf> T( new uqSamplerPdf );
	       T->initialize(); T->update();
	       return T;
	       }
     
     virtual boost::shared_ptr<msTreeMapper> clone() { 

            boost::shared_ptr<uqSamplerPdf> clone = New(); 
	    clone->msTreeMapper::operator=(*this);					      
	    return clone;
     }    

     boost::shared_ptr<msTreeMapper> setParameters(boost::shared_ptr<msGeneralizedCoordinates> coor){

        msTreeMapper::update(UqParameters,coor); 	
        if(!UqParameters->hasParent()) 		UqParameters->setAffiliation( mySharedPtr() );
        return mySharedPtr();
     }

     boost::shared_ptr<msTreeMapper> setModel(boost::shared_ptr<msScalarFunction> model){

        msTreeMapper::update(Model,model);
        if(!Model->hasParent()) 		Model->setAffiliation( mySharedPtr() );
        return mySharedPtr();
     }

     bool getNextPoint(){
          
	  bool ok = msSamplerExplicit::getNextPoint(UqParameters.getSharedPtr());
          if(ok)
	     for( size_t i=0;i<UqParameters->noOfDim();++i)
    	        Model->setConstant( (*UqParameters)[i]->getId(), (*UqParameters)[i]->Value);
          return ok;
     };

     boost::shared_ptr<msTreeMapper> getRndPoint(){
          
	 msSamplerExplicit::getRndPoint(UqParameters.getSharedPtr());
	 for( size_t i=0;i<UqParameters->noOfDim();++i)
    	     Model->setConstant( (*UqParameters)[i]->getId(), (*UqParameters)[i]->Value);
         return mySharedPtr();
     };
     boost::shared_ptr<msGeneralizedCoordinates> getUqParameters(){
          
	  return UqParameters.getSharedPtr();
     };
     
     boost::shared_ptr<msTreeMapper> set95CI();

     ostream& print(ostream& out) const;
    
private:

     msChild<msGeneralizedCoordinates> 	UqParameters;
     msChild<msScalarFunction> 		Model;
 };

std::ostream& operator<<(std::ostream& out,const uqSamplerPdf& sampler);

}
#endif // MSDIRACS_H
